﻿using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using System.Security.Cryptography;
using System.Text;

namespace CoreCms.Net.Core.SilkyCore.Utils
{
    public class AppDomainUtil
    {
        static AppDomainUtil()
        {
            EntryAssemblyName = Assembly.GetEntryAssembly().GetName().Name;
            MachineHash = GetMachineHash();
            CurrentProcessId = GetCurrentProcessId();
            IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            LocalAssemblies = LoadAssemblies();
        }

        public static List<Assembly> LocalAssemblies { get; private set; }

        public static string EntryAssemblyName { get; private set; }

        public static int MachineHash { get; private set; }

        public static int CurrentProcessId { get; private set; }

        public static bool IsWindows { get; }

        private static int GetMachineHash()
        {
            string hostName = Environment.MachineName;
            using var md5 = MD5.Create();
            var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(hostName));
            return (hash[0] << 16) + (hash[1] << 8) + hash[2]; // use first 3 bytes of hash
        }

        private static int GetCurrentProcessId()
        {
            return Process.GetCurrentProcess().Id;
        }

        private static List<Assembly> LoadAssemblies()
        {
            var list = new List<Assembly>();
            var deps = DependencyContext.Default;
            var libs = deps.CompileLibraries.Where(lib => !lib.Name.StartsWith("System.") && !lib.Name.StartsWith("Microsoft."));
            foreach (var lib in libs)
            {
                try
                {
                    var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                    list.Add(assembly);
                }
                catch
                {
                }
            }
            return list;
        }
    }
}